package com.powernode.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.powernode.constant.ProductConstants;
import com.powernode.domain.ProdProp;
import com.powernode.domain.ProdPropValue;
import com.powernode.exception.handler.BusinessException;
import com.powernode.mapper.ProdPropMapper;
import com.powernode.service.ProdPropService;
import com.powernode.service.ProdPropValueService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
@CacheConfig(cacheNames = "com.powernode.service.impl.ProdPropServiceImpl")
public class ProdPropServiceImpl extends ServiceImpl<ProdPropMapper, ProdProp> implements ProdPropService{

    @Autowired
    private ProdPropValueService prodPropValueService;

    @Autowired
    private ProdPropMapper prodPropMapper;

    /**
     * 分页查询属性信息
     *
     * @param propName
     * @param current
     * @param size
     * @return
     */
    @Override
    public Page<ProdProp> queryProdPropPage(String propName, Long current, Long size) {

        /**
         * 由于是多表查询,现在比较流行,使用单表进行查,然后再进行封装.而不是写一个连表SQL
         */

        Page page = new Page<ProdProp>(current,size);

        page = this.page(page,
                new LambdaQueryWrapper<ProdProp>()
                        .like(StringUtils.hasText(propName),ProdProp::getPropName,propName));

        List<ProdProp> records = page.getRecords();

        log.info(records.toString());

        // 将prodProp id提取出来
        List<Long> ProdPropId = records.stream().map(ProdProp::getPropId).collect(Collectors.toList());

        List<ProdPropValue> prodPropValues = prodPropValueService.list(new LambdaQueryWrapper<ProdPropValue>().in(ProdPropValue::getPropId, ProdPropId));

        // 将ProdPropValue装入ProdProp
        for (Object prodProp : records) {
            for (ProdPropValue prodPropValue : prodPropValues){
                ProdProp prodProp1 = (ProdProp) prodProp;
                if (prodPropValue.getPropId().equals(prodProp1.getPropId())){
                    prodProp1.getProdPropValues().add(prodPropValue);
                }
            }
        }

        return page;
    }

    /**
     * 新增属性信息
     *
     * @param prodProp 属性
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(key = ProductConstants.PROD_PROP_ALL_LIST_KEY)
    public Boolean saveProdSpec(ProdProp prodProp) {
        /**
         * 1.判断属性名为不为空,如果为空抛出异常
         * 2.首先判断属性名称是否存在,如果存在则抛出异常
         * 3.保存ProdProp 将返回的主键值 更新到ProdPropValue对象中,再保存ProdPropValue
         */
        if (prodProp == null || "".equals(prodProp.getPropName())){
            throw new BusinessException("属性名不能为空");
        }

        // 判断属性名存不存在

        List<ProdProp> DBProp = this.list(new LambdaQueryWrapper<ProdProp>().eq(ProdProp::getPropName, prodProp.getPropName()));

        if (DBProp != null && DBProp.size() > 0){
            throw new BusinessException("属性名已存在");
        }

        // 保存属性
        boolean save = this.save(prodProp);

        // 将主键值取出来,放到ProdPropValue中
        List<ProdPropValue> prodPropValues = prodProp.getProdPropValues();

        prodPropValues.stream().forEach(ppv -> {
            ppv.setPropId(prodProp.getPropId());
        });
        // 批量保存PPV
        prodPropValueService.saveBatch(prodPropValues);

        return save;
    }

    /**
     * 修改属性规格
     * @param prodProp
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(key = ProductConstants.PROD_PROP_ALL_LIST_KEY)
    public Boolean updateProdPropById(ProdProp prodProp) {
        /**
         * 1.修改ProdProp
         * 2.删除对应的PPV
         * 3.新增PPV
         */
        boolean b = this.updateById(prodProp);

        // 删除ppv
        List<ProdPropValue> prodPropValues = prodProp.getProdPropValues();

        prodPropValueService.remove(new LambdaQueryWrapper<ProdPropValue>().in(ProdPropValue::getPropId, prodProp.getPropId()));

        // 批量保存PPV
        // 将ProdProp中的主键值取出来,放到ProdPropValue中
        Long propId = prodProp.getPropId();
        prodPropValues.stream().forEach(ppv -> {
            ppv.setPropId(propId);
        });
        prodPropValueService.saveBatch(prodPropValues);

        return b;
    }

    /**
     * 根据prodPropId删除
     * @param prodPropId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(key = ProductConstants.PROD_PROP_ALL_LIST_KEY)
    public Boolean deleteByProdPropId(Long prodPropId) {
        /**
         * 1.删除ProdProp
         * 2.删除对应的PPV
         */
        boolean b = this.removeById(prodPropId);

        boolean remove = prodPropValueService.remove(new LambdaQueryWrapper<ProdPropValue>().eq(ProdPropValue::getPropId, prodPropId));

        return b;
    }

    /**
     * 查看所有商品规格,并不需要子属性
     *
     * @return
     */
    @Override
    @Cacheable(key = ProductConstants.PROD_PROP_ALL_LIST_KEY)
    public List<ProdProp> queryProdPropList() {
        // 查询所有的prodProp
        List<ProdProp> prodProps = this.list();

        // 并不需要查询子表
       /* if (prodProps == null ||  prodProps.size() < 0) {
            return  prodProps;
        }

        // 查询子表,并且将结果装进去
        // 收集所有的id
        List<Long> collect = prodProps.stream().map(ProdProp::getPropId).collect(Collectors.toList());

        // 查询子表
        List<ProdPropValue> prodPropValues = prodPropValueService.list(new LambdaQueryWrapper<ProdPropValue>().in(ProdPropValue::getPropId, collect));

        if (prodPropValues == null ||  prodPropValues.size() < 0) {
            return  prodProps;
        }
        // 将子表的数据装到父表中
        for (ProdPropValue prodPropValue : prodPropValues) {
            for (ProdProp prodProp : prodProps) {
                if(prodProp.getPropId().equals(prodPropValue.getPropId())) {
                    prodProp.getProdPropValues().add(prodPropValue);
                }
            }
        }*/

        return prodProps;
    }

}
